package edu.gyc.hiwxm.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.gyc.hiwxm.dao.BookingDao;
import edu.gyc.hiwxm.exception.BookingException;
import edu.gyc.hiwxm.model.Booking;
import edu.gyc.hiwxm.model.Girl;
import edu.gyc.hiwxm.model.Vip;
import edu.gyc.hiwxm.model.VipBooking;
import edu.gyc.hiwxm.myenum.BookingExceptionEnum;
import edu.gyc.hiwxm.myenum.BookingStatusEnum;
import edu.gyc.hiwxm.service.BookingService;
import edu.gyc.hiwxm.service.GirlService;
import edu.gyc.hiwxm.service.VipBookingService;
import edu.gyc.hiwxm.service.VipService;
import edu.gyc.hiwxm.util.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ls
 * @since 2020-01-01
 */
@Service
public class BookingServiceImpl extends ServiceImpl<BookingDao, Booking> implements BookingService {

    @Autowired
    private GirlService girlService;

    @Autowired
    private VipService vipService;

    @Autowired
    private VipBookingService vipBookingService;

    @Override
    public void schedual(String start, String end, int interval) {
        if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
            throw new BookingException("没有日期和时间，无法排班");
        }

        String startDate = start.substring(0, start.indexOf(" "));
        String endDate = end.substring(0, end.indexOf(" "));

        if (!startDate.equals(endDate)) {
            throw new BookingException("排班的起止日期必须是同一天！");
        }

        //查询该日期是否排班
        List<Booking> bookings = lambdaQuery().like(Booking::getWorkTime, startDate)
                .list();

        if (!bookings.isEmpty()) {
            throw new BookingException("已排班，不可重复排班！");
        }

        List<String> schedual = DateUtils.getTimeBlockList(start, end, interval);
        List<String> timePoints = DateUtils.getIntervalTimeList(start, end, interval);
        List<Girl> girls = girlService.list();
        for (Girl girl : girls) {
            Booking booking = new Booking();
            booking.setGirlId(girl.getId());
            booking.setBookingPrice(girl.getInitPrice());
            booking.setStatus(0);
            for (int i = 0; i < schedual.size(); i++) {
                booking.setTimeFrame(schedual.get(i));
                booking.setWorkTime(timePoints.get(i));
                save(booking);
            }

        }
    }

    @Override
    @Transactional
    public String booking(Integer userId, Integer girlId, Integer bookingId, Integer price) {
        Girl girl = girlService.getById(girlId);
        if (price == 0) {  //价格为零，表示为预订，则价格就是girl的初始价格
            price = girl.getInitPrice();
        }

        if (girl == null) {
            throw new BookingException(BookingExceptionEnum.GRIL_ID_ERROR.getMessage());

        }
        Vip vip = vipService.getById(userId);
        if (vip == null) {
            throw new BookingException(BookingExceptionEnum.VIP_ID_ERROR.getMessage());
        }

        String msg = "Sorry, " + vip.getName() + " booking fail. 你的预付款不足，请充值！";
        Booking booking = lambdaQuery().eq(Booking::getId, bookingId).one();
        if (booking == null) {
            throw new BookingException(BookingExceptionEnum.BOOKING_ID_ERROR.getMessage());
        }

        //预订，检查客户余额大于初始价,可预订
        if (booking.getStatus().equals(BookingStatusEnum.PRE_BOOKING.getStatus()) && vip.getSubscriptionFee() >= girl.getInitPrice()) {
            vipService.lambdaUpdate().eq(Vip::getId, userId)
                    .set(Vip::getSubscriptionFee, vip.getSubscriptionFee() - price).update();

            boolean r = lambdaUpdate().set(Booking::getStatus, BookingStatusEnum.END_BOOKING.getStatus()).set(Booking::getUserId, userId).set(Booking::getBookingPrice, price)
                    .eq(Booking::getId, bookingId).update();
            if (r) {
                msg = "恭喜，" + vip.getName() + " 预订 " + girl.getName() + " 成功，她将在" + booking.getWorkTime() + " 为你服务！";
            }
        }
        //已预订，检查出价大于预订价可抢单,抢单成功后应该归还被抢单者的消费金
        if (booking.getStatus().equals(BookingStatusEnum.END_BOOKING.getStatus()) && price > booking.getBookingPrice()) {
            int balance = vip.getSubscriptionFee() - price;
            if (balance < 0) {
                throw new BookingException(BookingExceptionEnum.MONENY_NOT_ENOUGH.getMessage());
            }
            //归还被迁单者预订金
            int backMoney = booking.getBookingPrice();
            int backUserId = booking.getUserId();

            vipService.lambdaUpdate().eq(Vip::getId, backUserId)
                    .set(Vip::getSubscriptionFee, vip.getSubscriptionFee() - price).update();
            boolean r = lambdaUpdate().set(Booking::getStatus, BookingStatusEnum.END_BOOKING.getStatus()).set(Booking::getUserId, userId).set(Booking::getBookingPrice, price)
                    .eq(Booking::getId, bookingId).update();
            if (r) {
                msg = "恭喜抢单成功，" + vip.getName() + " 预订 " + girl.getName() + " 成功，她将在" + booking.getWorkTime() + " 为你服务！";
                //还钱
                Vip backVip = vipService.getById(backUserId);
                vipService.lambdaUpdate().eq(Vip::getId, backUserId)
                        .set(Vip::getSubscriptionFee, backVip.getSubscriptionFee() + backMoney).update();

                //还钱的消费记录也要存储
                VipBooking vipBooking = new VipBooking();
                vipBooking.setGirlId(girlId);
                vipBooking.setConsumptionPrice(booking.getBookingPrice());
                vipBooking.setWorkTime(booking.getWorkTime());
                vipBooking.setTransactionTime(LocalDateTime.now());
                vipBooking.setUserId(backUserId);
                vipBookingService.save(vipBooking);
            }
        }

        //存储消费记录
        VipBooking vipBooking = new VipBooking();
        vipBooking.setGirlId(girlId);
        vipBooking.setConsumptionPrice(-price);  //消费是花钱，故而为负
        vipBooking.setWorkTime(booking.getWorkTime());
        vipBooking.setTransactionTime(LocalDateTime.now());
        vipBooking.setUserId(userId);
        vipBookingService.save(vipBooking);
        return msg;


    }

    @Override
    public String booking(Integer userId, Integer girlId, Integer bookingId) {

        return booking(userId, girlId, bookingId, 0);

    }

    @Override
    public List<Booking> getGirlBookingReport(String bookingDate, Integer giriId) {
        if (StringUtils.isBlank(bookingDate)) {
            throw new BookingException("请选择预约日期！");
        }
        //查询该日期是否排班
        List<Booking> bookings = lambdaQuery().like(Booking::getWorkTime, bookingDate)
                .eq(Booking::getGirlId, giriId)
                .list();

        if (bookings.isEmpty()) {
            throw new BookingException("还未排班，请通知管理员排班！");
        }

        Girl girl = girlService.getById(bookings.get(0).getGirlId());
        for (Booking booking : bookings) {

            booking.setGirlName(girl.getName());
            if (booking.getUserId() != null) {
                Vip vip = vipService.getById(booking.getUserId());
                booking.setUserName(vip.getName());
            }
        }
        return bookings;
    }

    @Override
    public List<Booking> getVipBookingReport(Integer userId) {
        List<Booking> bookings = lambdaQuery().eq(Booking::getUserId, userId)
                .orderByDesc(Booking::getWorkTime)
                .list();
        for (Booking booking : bookings) {
            Girl girl = girlService.getById(booking.getGirlId());
            booking.setGirlName(girl.getName());
            if (booking.getUserId() != null) {
                Vip vip = vipService.getById(booking.getUserId());
                booking.setUserName(vip.getName());
            }
        }
        return bookings;
    }

    @Override
    public List<Booking> getAllGirlBookingReport() {
        List<Booking> bookings = list();
        for (Booking booking : bookings) {
            Girl girl = girlService.getById(booking.getGirlId());
            booking.setGirlName(girl.getName());
            if (booking.getUserId() != null) {
                Vip vip = vipService.getById(booking.getUserId());
                booking.setUserName(vip.getName());
            }


        }
        return bookings;
    }
}
